/**
 *  @file: ConsoleTask.h
 *  @author: nwz
 *  @brief: 
 *  @date: 2024��7��25��
 * 
 */

#pragma once
#include "basic_header.h"

#ifndef TAG
#define TAG "console"
#endif

#define LOG_BASE(level,...) task::ConsoleTask::getInstance().log(level,(const uint8_t*)TAG,__VA_ARGS__)

#define LOG_D(...)	LOG_BASE(task::ConsoleTask::LogLevel::DEBUG, __VA_ARGS__)
#define LOG_I(...)	LOG_BASE(task::ConsoleTask::LogLevel::INFO, __VA_ARGS__)
#define LOG_W(...)	LOG_BASE(task::ConsoleTask::LogLevel::WARN, __VA_ARGS__)
#define LOG_E(...)	LOG_BASE(task::ConsoleTask::LogLevel::ERR, __VA_ARGS__)

#define LOG_SYNC(...)  task::ConsoleTask::getInstance().logSync(__VA_ARGS__)

namespace task {

/*
 *
 */
class ConsoleTask {

public:
	enum class LogLevel : uint8_t {
		DEBUG, INFO, WARN, ERR
	};
	static ConsoleTask& getInstance();

	int init();
	void log(LogLevel level, const uint8_t *tag, const void *fmt, ...);
	int write(const uint8_t *data, uint32_t len);
	int read(uint8_t *data, uint32_t len, uint32_t timeout = 100);
	void setLevel(LogLevel lv) {
		this->lv = lv;
	}

	static void writeLoop(ConsoleTask *arg);
	static void readLoop(ConsoleTask *arg);
	static void test1();

	static void logSync(const void *fmt, ...);

private:
	ConsoleTask();
	virtual ~ConsoleTask();
	ConsoleTask(const ConsoleTask &task) = delete;
	const ConsoleTask &operator=(const ConsoleTask &task) = delete;

	LogLevel lv = CONSOLE_LOG_LEVEL;

	SemaphoreHandle_t send_mutex;
	StreamBufferHandle_t send_stream_buffer;

	MessageBufferHandle_t read_message_buffer;

	void sendDataToUserRead(const uint8_t *data, uint32_t len);

};

} /* namespace task */
